// 压缩配置接口
export interface CompressionOptions {
  maxWidth?: number;      // 最大宽度
  maxHeight?: number;     // 最大高度  
  quality?: number;       // 图片质量 0-1
  mimeType?: string;      // 输出格式
  maintainAspectRatio?: boolean; // 保持宽高比
}

// 压缩结果接口
export interface CompressionResult {
  file: File;                    // 压缩后的文件
  originalSize: number;          // 原始文件大小
  compressedSize: number;        // 压缩后文件大小
  compressionRatio: string;      // 压缩比例
  width: number;                 // 压缩后宽度
  height: number;                // 压缩后高度
}

// 压缩信息接口
export interface CompressionInfo {
  originalSize: number;
  compressedSize: number;
  compressionRatio: string;
}

/**
 * 图片压缩工具类
 */
class ImageCompressUtil {
  /**
   * 基础图片压缩方法
   */
  static async compressImage(file: File, options: CompressionOptions = {}): Promise<CompressionResult> {
    return new Promise((resolve, reject) => {
      const {
        maxWidth = 1920,
        maxHeight = 1080,
        quality = 0.8,
        mimeType = 'image/jpeg',
        maintainAspectRatio = true
      } = options;

      // 验证文件类型
      if (!file.type.startsWith('image/')) {
        reject(new Error('请选择图片文件'));
        return;
      }

      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      const img = new Image();
      
      img.onload = () => {
        try {
          let { width, height } = img;
          const originalWidth = width;
          const originalHeight = height;
          
          // 计算缩放比例
          if (width > maxWidth || height > maxHeight) {
            const ratio = maintainAspectRatio 
              ? Math.min(maxWidth / width, maxHeight / height)
              : Math.max(maxWidth / width, maxHeight / height);
            
            width *= ratio;
            height *= ratio;
          }
          
          // 设置canvas尺寸
          canvas.width = Math.round(width);
          canvas.height = Math.round(height);
          
          // 使用白色背景填充（针对PNG透明背景）
          ctx!.fillStyle = '#FFFFFF';
          ctx!.fillRect(0, 0, canvas.width, canvas.height);
          
          // 绘制图片
          ctx!.drawImage(img, 0, 0, canvas.width, canvas.height);
          
          // 转换为Blob
          canvas.toBlob(
            (blob) => {
              if (blob) {
                // 创建压缩后的文件对象
                const compressedFile = new File(
                  [blob],
                  this.getOutputFileName(file.name, mimeType),
                  { 
                    type: mimeType, 
                    lastModified: Date.now() 
                  }
                );

                const compressionRatio = ((1 - blob.size / file.size) * 100).toFixed(1);
                
                resolve({
                  file: compressedFile,
                  originalSize: file.size,
                  compressedSize: blob.size,
                  compressionRatio,
                  width: Math.round(width),
                  height: Math.round(height)
                });
              } else {
                reject(new Error('图片压缩失败'));
              }
            },
            mimeType,
            quality
          );
        } catch (error) {
          reject(error);
        }
      };
      
      img.onerror = () => reject(new Error('图片加载失败'));
      img.src = URL.createObjectURL(file);
    });
  }

  /**
   * 智能压缩 - 根据文件大小自动调整压缩参数
   */
  static async smartCompress(file: File): Promise<CompressionResult> {
    const fileSizeMB = file.size / 1024 / 1024;
    let options: CompressionOptions = {};
    
    if (fileSizeMB > 5) {
      // 大于5MB的图片使用较强压缩
      options = { 
        quality: 0.6, 
        maxWidth: 1600, 
        maxHeight: 900,
        mimeType: 'image/jpeg'
      };
    } else if (fileSizeMB > 2) {
      // 2-5MB的图片使用中等压缩
      options = { 
        quality: 0.7, 
        maxWidth: 1920, 
        maxHeight: 1080,
        mimeType: 'image/jpeg'
      };
    } else if (fileSizeMB > 1) {
      // 1-2MB的图片使用轻度压缩
      options = { 
        quality: 0.8, 
        maxWidth: 1920, 
        maxHeight: 1080,
        mimeType: 'image/jpeg'
      };
    } else if (fileSizeMB > 0.5) {
      // 0.5-1MB的图片基本不压缩，只调整尺寸
      options = { 
        quality: 0.9, 
        maxWidth: 2560, 
        maxHeight: 1440,
        mimeType: 'image/jpeg'
      };
    } else {
      // 小于500KB的图片返回原文件（实际还是会轻微压缩）
      options = { 
        quality: 0.95, 
        maxWidth: 3840, 
        maxHeight: 2160,
        mimeType: file.type // 保持原格式
      };
    }
    
    return await this.compressImage(file, options);
  }

  /**
   * 快速压缩 - 适用于大多数场景
   */
  static async quickCompress(file: File): Promise<CompressionResult> {
    return await this.compressImage(file, {
      quality: 0.8,
      maxWidth: 1920,
      maxHeight: 1080,
      mimeType: 'image/jpeg'
    });
  }

  /**
   * 高质量压缩 - 保持较高画质
   */
  static async highQualityCompress(file: File): Promise<CompressionResult> {
    return await this.compressImage(file, {
      quality: 0.9,
      maxWidth: 2560,
      maxHeight: 1440,
      mimeType: 'image/jpeg'
    });
  }

  /**
   * 极速压缩 - 适用于缩略图等场景
   */
  static async fastCompress(file: File): Promise<CompressionResult> {
    return await this.compressImage(file, {
      quality: 0.6,
      maxWidth: 800,
      maxHeight: 600,
      mimeType: 'image/jpeg'
    });
  }

  /**
   * 检查是否需要压缩
   */
  static needCompress(file: File, maxSizeKB: number = 500): boolean {
    return file.size > maxSizeKB * 1024;
  }

  /**
   * 获取压缩信息
   */
  static getCompressionInfo(originalSize: number, compressedSize: number): CompressionInfo {
    const compressionRatio = ((1 - compressedSize / originalSize) * 100).toFixed(1);
    return {
      originalSize,
      compressedSize,
      compressionRatio
    };
  }

  /**
   * 生成输出文件名
   */
  private static getOutputFileName(originalName: string, mimeType: string): string {
    const ext = mimeType.split('/')[1];
    const nameWithoutExt = originalName.replace(/\.[^/.]+$/, "");
    return `${nameWithoutExt}_compressed.${ext}`;
  }

  /**
   * 获取文件大小描述
   */
  static getFileSizeDescription(bytes: number): string {
    if (bytes < 1024) {
      return `${bytes} B`;
    } else if (bytes < 1024 * 1024) {
      return `${(bytes / 1024).toFixed(2)} KB`;
    } else {
      return `${(bytes / 1024 / 1024).toFixed(2)} MB`;
    }
  }
}

export default ImageCompressUtil;